package com.insight.modules.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.insight.common.system.vo.LoginUser;
import com.insight.modules.system.controller.SysRoleController;
import com.insight.modules.system.entity.SysRole;
import com.insight.modules.system.entity.SysUserRole;
import com.insight.modules.system.mapper.SysRoleMapper;
import com.insight.modules.system.mapper.SysUserMapper;
import com.insight.modules.system.mapper.SysUserRoleMapper;
import com.insight.modules.system.service.ISysUserRoleService;
import com.insight.modules.system.vo.SysUserRoleVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户角色表 服务实现类
 * </p>
 *
 * @Author scott
 * @since 2018-12-21
 */
@Service
public class SysUserRoleServiceImpl extends MPJBaseServiceImpl<SysUserRoleMapper, SysUserRole> implements ISysUserRoleService {

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 根据角色编码查询该角色下的用户信息列表
     *
     * @param id 角色ID
     * @return 返回对应角色下的用户登录信息列表
     */
    @Override
    public List<LoginUser> getUsersByRoleCode(String id) {
        return super.baseMapper.getUsersByRoleCode(id);
    }

    /**
     * 根据用户ID查询用户所拥有的角色编码列表
     *
     * @param userid 用户ID
     * @return 角色编码字符串列表
     */
    @Override
    public List<String> getUserRoleByUserId(String userid) {
        return sysUserRoleMapper.getRoleCodeByuserId(userid);
    }

    /**
     * 给用户授予角色
     *
     * @param sysUserRoleVO 包含角色ID和用户ID列表的对象
     * 逻辑说明：
     *  1. 对每个用户检查是否已存在该角色关联，避免重复插入；
     *  2. 若用户已拥有“三权角色”或目标角色是三权角色，先删除该用户所有角色，再赋予新角色；
     *  3. 否则直接新增用户角色关联。
     */
    @Override
    public void grantRole(SysUserRoleVO sysUserRoleVO) {
        String sysRoleId = sysUserRoleVO.getRoleId();
        for (String sysUserId : sysUserRoleVO.getUserIdList()) {
            QueryWrapper<SysUserRole> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("role_id", sysRoleId).eq("user_id", sysUserId);

            SysUserRole sysUserRole = new SysUserRole(sysUserId, sysRoleId);

            // 获取系统定义的“三权角色”
            List<String> roles = SysRoleController.getThreePowersRole();

            // 查询用户当前的角色编码
            List<String> grantRoles = super.baseMapper.getRoleCodeByUserId(sysUserId);

            // 获取当前操作的角色信息
            SysRole sysRole = sysRoleMapper.selectById(sysRoleId);

            // 如果用户当前拥有三权角色或当前角色是三权角色，先删除用户所有角色
            if ((CollUtil.isNotEmpty(roles) && grantRoles.stream().anyMatch(roles::contains)) || roles.contains(sysRole.getRoleCode())) {
                super.baseMapper.delete(new LambdaQueryWrapper<SysUserRole>()
                        .eq(SysUserRole::getUserId, sysUserId));
            }

            // 检查是否已存在该用户角色关联，避免重复添加
            SysUserRole one = baseMapper.selectOne(queryWrapper);
            if (one == null) {
                baseMapper.insert(sysUserRole);
            }
        }
    }

    /**
     * 根据用户ID列表查询对应的角色名称和角色编码信息
     *
     * @param userIds 用户ID列表
     * @return Map<String, String> 返回键为"userId_names"和"userId_codes"格式的角色名称及编码拼接字符串
     */
    @Override
    public Map<String, String> getRoleByUserIds(List<String> userIds) {
        // 从数据库查询用户角色对应关系
        List<SysUserRoleVO> list = sysUserMapper.getRoleByUserIds(userIds);

        Map<String, String> res = new HashMap<>();

        list.forEach(item -> {
            String userId = item.getUserId();
            String roleName = item.getRoleName();
            String roleCode = item.getRoleCode();

            // 追加角色名称，格式：userId_names -> "角色1,角色2"
            String existingRoleNames = res.getOrDefault(userId + "_names", "");
            res.put(userId + "_names", existingRoleNames.isEmpty() ? roleName : existingRoleNames + "," + roleName);

            // 追加角色编码，格式：userId_codes -> "code1,code2"
            String existingRoleCodes = res.getOrDefault(userId + "_codes", "");
            res.put(userId + "_codes", existingRoleCodes.isEmpty() ? roleCode : existingRoleCodes + "," + roleCode);
        });
        return res;
    }
}

